package com.spzx.cart.service.impl;

import com.spzx.cart.api.RemoteCartService;
import com.spzx.cart.api.domain.CartInfo;
import com.spzx.cart.service.ICartService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.api.domain.vo.SkuPrice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class CartServiceImpl implements ICartService {

    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    RemoteProductService remoteProductService;

    @Override
    public void addToCart(Long skuId, Integer num) {
     //构建购物车key
        Long userId= SecurityContextHolder.getUserId();//通过线程获取用户id
        String cartKey=getCartKey(userId);//大key
        String hashKey=String.valueOf(skuId);//小key
        //判断商品是否添加过
        BoundHashOperations<String,String, CartInfo> boundHashOperations=redisTemplate.boundHashOps(cartKey);
        int threshold=99;//阈值
        if (boundHashOperations.hasKey(hashKey)){//添加过
            CartInfo cartInfo=boundHashOperations.get(hashKey);
            int total = cartInfo.getSkuNum() + num;
            cartInfo.setSkuNum(total>threshold?threshold:total);
            cartInfo.setUpdateTime(new Date());
            boundHashOperations.put(hashKey,cartInfo);
        }else {//首次添加
            Long size = boundHashOperations.size();
            if (++size>50){
                throw new ServiceException("商品不能超过50");
            }
            CartInfo cartInfo=new CartInfo();
            cartInfo.setUserId(userId);
            cartInfo.setSkuId(skuId);
            cartInfo.setUpdateTime(new Date());
            //远程调用
            R<ProductSku> productSkuResult=remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            if (R.FAIL==productSkuResult.getCode()){//状态码 500 远程调用降级处理
                throw new ServiceException(productSkuResult.getMsg());//交给统一异常处理器
            }
            ProductSku productSku=productSkuResult.getData();
            cartInfo.setCartPrice(productSku.getSalePrice());//购物车价格 当时添加购物车的价格
            cartInfo.setSkuPrice(productSku.getSalePrice());//可能变化的 实时价格
            cartInfo.setSkuNum(num);
            cartInfo.setThumbImg(productSku.getThumbImg());
            cartInfo.setSkuName(productSku.getSkuName());
            cartInfo.setIsChecked(1);
            boundHashOperations.put(hashKey,cartInfo);
        }

    }

    private String getCartKey(Long userId){
        String cartKey="user:cart:"+userId;
        return cartKey;
    }

    @Override
    public List<CartInfo> getCartList() {
        Long userId=SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> boundHashOperations=redisTemplate.boundHashOps(cartKey);
        List<CartInfo> values = boundHashOperations.values();
        if (CollectionUtils.isEmpty(values)){
            return new ArrayList<>();
        }
        //创建时间倒序排序
        List<CartInfo> sortedValues = values.stream().sorted((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime())).toList();
        //回显数据库商品最新价格
        List<Long> skuIdList = sortedValues.stream().map(CartInfo::getSkuId).toList();
        //远程调用
        R<List<SkuPrice>> skuPriceResult=remoteProductService.getSkuPriceList(skuIdList,SecurityConstants.INNER);
        if (R.FAIL==skuPriceResult.getCode()){
            throw  new ServiceException(skuPriceResult.getMsg());
        }
        List<SkuPrice> skuPriceList=skuPriceResult.getData();
        //List<SkuPrice> 转为 Map<Long, BigDecimal>
        Map<Long, BigDecimal> skuIdToSalePriceMap=skuPriceList.stream().collect(
                Collectors.toMap(SkuPrice::getSkuId,SkuPrice::getSalePrice)
        );

        for (CartInfo cartInfo : sortedValues) {
            Long skuId = cartInfo.getSkuId();
            BigDecimal salePrice = skuIdToSalePriceMap.get(skuId);
            cartInfo.setSkuPrice(salePrice);
        }
        return sortedValues;
    }

    @Override
    public void deleteCart(Long skuId) {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        String hashKey = String.valueOf(skuId);
        BoundHashOperations<String,String,CartInfo> boundHashOperations=redisTemplate.boundHashOps(cartKey);
        if (boundHashOperations.hasKey(hashKey)){
            boundHashOperations.delete(hashKey);
        }
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        String hashKey = String.valueOf(skuId);
        BoundHashOperations<String,String,CartInfo> boundHashOperations=redisTemplate.boundHashOps(cartKey);
        if (boundHashOperations.hasKey(hashKey)){
            CartInfo cartInfo = boundHashOperations.get(hashKey);
            cartInfo.setIsChecked(isChecked);
            boundHashOperations.put(hashKey,cartInfo);
        }
    }

    @Override
    public void allCheckCart(Integer isChecked) {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> boundHashOperations=redisTemplate.boundHashOps(cartKey);
        List<CartInfo> values = boundHashOperations.values();
        if (!CollectionUtils.isEmpty(values)){
            for (CartInfo cartInfo : values) {
                cartInfo.setIsChecked(isChecked);
                boundHashOperations.put(cartInfo.getSkuId().toString(),cartInfo);
            }
        }
    }

    @Override
    public void clearCart() {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        redisTemplate.delete(cartKey);
    }

    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        List<CartInfo> cartInfoList=new ArrayList<>();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> boundHashOperations=redisTemplate.boundHashOps(cartKey);
        List<CartInfo> values = boundHashOperations.values();
        if (!CollectionUtils.isEmpty(values)){
            for (CartInfo cartInfo : values) {
                if (cartInfo.getIsChecked()==1){
                    cartInfoList.add(cartInfo);
                }
            }
        }
        return cartInfoList;
    }

    @Override
    public Boolean updateCartPrice(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> boundHashOperations=redisTemplate.boundHashOps(cartKey);
        List<CartInfo> values = boundHashOperations.values();
        //获取商品价格
        List<Long> skuIdList = values.stream().map(CartInfo::getSkuId).toList();
        //远程调用
        R<List<SkuPrice>> skuPriceListResult = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
        if (R.FAIL==skuPriceListResult.getCode()){
            throw new ServiceException(skuPriceListResult.getMsg());
        }
        List<SkuPrice> skuPriceList = skuPriceListResult.getData();
        //List 转为 Map
        Map<Long, BigDecimal> skuIdToSkuPriceMap = skuPriceList.stream().
                collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
        for (CartInfo cartInfo : values) {
            if (cartInfo.getIsChecked()==1){
                cartInfo.setCartPrice(skuIdToSkuPriceMap.get(cartInfo.getSkuId()));
                cartInfo.setSkuPrice(skuIdToSkuPriceMap.get(cartInfo.getSkuId()));
                boundHashOperations.put(cartInfo.getSkuId().toString(),cartInfo);
            }
        }
        return true;
    }

    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        String cartKey = getCartKey(userId);
        BoundHashOperations<String,String,CartInfo> boundHashOperations=redisTemplate.boundHashOps(cartKey);
        List<CartInfo> values = boundHashOperations.values();
        if (!CollectionUtils.isEmpty(values)){
            for (CartInfo cartInfo : values) {
                if (cartInfo.getIsChecked()==1){
                    redisTemplate.delete(cartInfo.getSkuId().toString());
                }
            }
        }
        return true;
    }
}